<template>
  <div 
    :class="[
      'bx-select',
      'bx-glass',
      {
        'bx-select--disabled': disabled,
        'bx-select--open': visible,
        'bx-select--multiple': multiple,
        [`bx-select--${size}`]: size
      }
    ]"
    @click="handleToggle"
  >
    <div class="bx-select__selection">
      <!-- 多选标签 -->
      <template v-if="multiple && selectedOptions.length">
        <BxTag
          v-for="option in selectedOptions"
          :key="option.value"
          :closable="!disabled"
          size="small"
          @close="handleRemoveTag(option)"
        >
          {{ option.label }}
        </BxTag>
      </template>
      
      <!-- 单选显示 -->
      <span 
        v-else-if="!multiple && selectedOption"
        class="bx-select__selected-text"
      >
        {{ selectedOption.label }}
      </span>
      
      <!-- 占位符 -->
      <span 
        v-else
        class="bx-select__placeholder"
      >
        {{ placeholder }}
      </span>
    </div>

    <div class="bx-select__suffix">
      <BxIcon 
        v-if="clearable && hasValue && !disabled"
        name="x"
        class="bx-select__clear"
        @click.stop="handleClear"
      />
      <BxIcon 
        :name="visible ? 'chevron-up' : 'chevron-down'"
        class="bx-select__arrow"
      />
    </div>

    <!-- 下拉面板 -->
    <teleport to="body">
      <div 
        v-if="visible"
        ref="dropdownRef"
        :class="[
          'bx-select__dropdown',
          'bx-glass'
        ]"
        :style="dropdownStyle"
      >
        <div 
          v-if="filterable"
          class="bx-select__search"
        >
          <BxInput 
            v-model="searchValue"
            :placeholder="searchPlaceholder"
            size="small"
            @input="handleSearch"
          />
        </div>
        
        <div class="bx-select__options">
          <div 
            v-if="filteredOptions.length === 0"
            class="bx-select__empty"
          >
            {{ emptyText }}
          </div>
          
          <slot v-else>
            <BxOption
              v-for="option in filteredOptions"
              :key="option.value"
              :value="option.value"
              :label="option.label"
              :disabled="option.disabled"
            />
          </slot>
        </div>
      </div>
    </teleport>
  </div>
</template>

<script>
import { ref, computed, provide, nextTick, onMounted, onUnmounted } from 'vue'
import BxIcon from '../basic/BxIcon.vue'
import BxTag from '../data-display/BxTag.vue'
import BxInput from './BxInput.vue'

export default {
  name: 'BxSelect',
  components: {
    BxIcon,
    BxTag,
    BxInput
  },
  props: {
    modelValue: {
      type: [String, Number, Array],
      default: ''
    },
    options: {
      type: Array,
      default: () => []
    },
    placeholder: {
      type: String,
      default: '请选择'
    },
    size: {
      type: String,
      default: 'medium',
      validator: (value) => ['small', 'medium', 'large'].includes(value)
    },
    disabled: {
      type: Boolean,
      default: false
    },
    clearable: {
      type: Boolean,
      default: false
    },
    multiple: {
      type: Boolean,
      default: false
    },
    filterable: {
      type: Boolean,
      default: false
    },
    searchPlaceholder: {
      type: String,
      default: '搜索选项'
    },
    emptyText: {
      type: String,
      default: '暂无数据'
    }
  },
  emits: ['update:modelValue', 'change', 'clear'],
  setup(props, { emit }) {
    const visible = ref(false)
    const searchValue = ref('')
    const dropdownRef = ref(null)
    const dropdownStyle = ref({})

    const selectedValues = computed(() => {
      if (props.multiple) {
        return Array.isArray(props.modelValue) ? props.modelValue : []
      }
      return props.modelValue !== undefined && props.modelValue !== null ? [props.modelValue] : []
    })

    const selectedOptions = computed(() => {
      return props.options.filter(option => selectedValues.value.includes(option.value))
    })

    const selectedOption = computed(() => {
      return props.options.find(option => option.value === props.modelValue)
    })

    const hasValue = computed(() => {
      if (props.multiple) {
        return selectedValues.value.length > 0
      }
      return props.modelValue !== undefined && props.modelValue !== null && props.modelValue !== ''
    })

    const filteredOptions = computed(() => {
      if (!props.filterable || !searchValue.value) {
        return props.options
      }
      
      return props.options.filter(option => 
        option.label.toLowerCase().includes(searchValue.value.toLowerCase())
      )
    })

    const updatePosition = async () => {
      if (!dropdownRef.value) return

      await nextTick()
      
      const selectElement = document.querySelector('.bx-select')
      if (!selectElement) return

      const selectRect = selectElement.getBoundingClientRect()
      const dropdownRect = dropdownRef.value.getBoundingClientRect()
      const viewportHeight = window.innerHeight

      let top = selectRect.bottom + 8
      let left = selectRect.left

      // 检查是否超出视口底部
      if (top + dropdownRect.height > viewportHeight - 8) {
        top = selectRect.top - dropdownRect.height - 8
      }

      // 检查是否超出视口右侧
      if (left + dropdownRect.width > window.innerWidth - 8) {
        left = window.innerWidth - dropdownRect.width - 8
      }

      // 检查是否超出视口左侧
      if (left < 8) {
        left = 8
      }

      dropdownStyle.value = {
        position: 'fixed',
        top: `${top}px`,
        left: `${left}px`,
        minWidth: `${selectRect.width}px`,
        zIndex: 1000
      }
    }

    const show = async () => {
      if (props.disabled) return
      visible.value = true
      await updatePosition()
    }

    const hide = () => {
      visible.value = false
      searchValue.value = ''
    }

    const handleToggle = () => {
      visible.value ? hide() : show()
    }

    const handleSelect = (value) => {
      if (props.multiple) {
        const newValues = [...selectedValues.value]
        const index = newValues.indexOf(value)
        
        if (index > -1) {
          newValues.splice(index, 1)
        } else {
          newValues.push(value)
        }
        
        emit('update:modelValue', newValues)
        emit('change', newValues)
      } else {
        emit('update:modelValue', value)
        emit('change', value)
        hide()
      }
    }

    const handleRemoveTag = (option) => {
      if (props.disabled) return
      
      const newValues = selectedValues.value.filter(val => val !== option.value)
      emit('update:modelValue', newValues)
      emit('change', newValues)
    }

    const handleClear = () => {
      const newValue = props.multiple ? [] : ''
      emit('update:modelValue', newValue)
      emit('change', newValue)
      emit('clear')
    }

    const handleSearch = (value) => {
      searchValue.value = value
    }

    const handleClickOutside = (event) => {
      const selectElement = document.querySelector('.bx-select')
      if (!selectElement?.contains(event.target) && 
          !dropdownRef.value?.contains(event.target)) {
        hide()
      }
    }

    // 提供给子组件的上下文
    provide('bx-select', {
      selectedValues,
      handleSelect
    })

    onMounted(() => {
      document.addEventListener('click', handleClickOutside)
      window.addEventListener('resize', updatePosition)
      window.addEventListener('scroll', updatePosition)
    })

    onUnmounted(() => {
      document.removeEventListener('click', handleClickOutside)
      window.removeEventListener('resize', updatePosition)
      window.removeEventListener('scroll', updatePosition)
    })

    return {
      visible,
      searchValue,
      dropdownRef,
      dropdownStyle,
      selectedOptions,
      selectedOption,
      hasValue,
      filteredOptions,
      handleToggle,
      handleRemoveTag,
      handleClear,
      handleSearch
    }
  }
}
</script>

<style scoped>
.bx-select {
  position: relative;
  display: flex;
  align-items: center;
  min-height: 40px;
  padding: 0 12px;
  border: 1px solid var(--bx-glass-border);
  border-radius: var(--bx-radius-medium);
  background: var(--bx-glass-bg);
  backdrop-filter: var(--bx-glass-blur);
  cursor: pointer;
  transition: all var(--bx-transition-medium);
  font-family: var(--bx-font-family);
}

.bx-select:hover {
  border-color: var(--bx-glass-border-hover);
  background: var(--bx-glass-bg-hover);
}

.bx-select--open {
  border-color: rgba(0, 122, 255, 0.5);
  box-shadow: 0 0 0 2px rgba(0, 122, 255, 0.1);
}

.bx-select--disabled {
  opacity: 0.6;
  cursor: not-allowed;
  background: rgba(255, 255, 255, 0.03);
}

.bx-select--small {
  min-height: 32px;
  padding: 0 8px;
  font-size: 13px;
}

.bx-select--large {
  min-height: 48px;
  padding: 0 16px;
  font-size: 16px;
}

.bx-select__selection {
  flex: 1;
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 4px;
  min-width: 0;
}

.bx-select--multiple .bx-select__selection {
  padding: 4px 0;
}

.bx-select__selected-text {
  color: var(--bx-text-primary);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.bx-select__placeholder {
  color: var(--bx-text-tertiary);
}

.bx-select__suffix {
  display: flex;
  align-items: center;
  gap: 4px;
  margin-left: 8px;
}

.bx-select__clear {
  font-size: 14px;
  color: var(--bx-text-tertiary);
  cursor: pointer;
  transition: color var(--bx-transition-medium);
}

.bx-select__clear:hover {
  color: var(--bx-text-primary);
}

.bx-select__arrow {
  font-size: 12px;
  color: var(--bx-text-tertiary);
  transition: transform var(--bx-transition-medium);
}

.bx-select--open .bx-select__arrow {
  transform: rotate(180deg);
}

.bx-select__dropdown {
  background: var(--bx-glass-bg);
  backdrop-filter: var(--bx-glass-blur-strong);
  border: 1px solid var(--bx-glass-border);
  border-radius: var(--bx-radius-medium);
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.15);
  max-height: 256px;
  overflow: hidden;
  animation: bx-select-dropdown-fade-in 0.2s ease-out;
}

.bx-select__search {
  padding: 8px;
  border-bottom: 1px solid var(--bx-glass-border);
}

.bx-select__options {
  max-height: 200px;
  overflow-y: auto;
  padding: 4px 0;
}

.bx-select__empty {
  padding: 12px 16px;
  text-align: center;
  color: var(--bx-text-tertiary);
  font-size: 14px;
}

@keyframes bx-select-dropdown-fade-in {
  0% {
    opacity: 0;
    transform: translateY(-8px);
  }
  100% {
    opacity: 1;
    transform: translateY(0);
  }
}

/* 响应式设计 */
@media (max-width: 768px) {
  .bx-select {
    min-height: 36px;
    padding: 0 10px;
  }
  
  .bx-select--small {
    min-height: 30px;
    padding: 0 8px;
  }
  
  .bx-select--large {
    min-height: 42px;
    padding: 0 14px;
  }
}
</style>

